package com.rtsapp.server.domain;

import com.rtsapp.server.bytecode.ClassGenerator;
import com.rtsapp.server.logger.Logger;
import com.rtsapp.server.utils.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by admin on 15-9-19.
 * EntityBuilder 用于注册 实体类型, 创建新实体实例
 */
public final class EntityBuilder {

    private static final Logger logger =com.rtsapp.server.logger.LoggerFactory.getLogger( EntityBuilder.class );
    private static final Map<Class<?>, Class<?> > entityImplClasses = new HashMap<>( );

    /**
     * 注册一个实体类型
     * @param entityClass
     */
    public static void registerEntity( Class<?> entityClass ){
        if( !entityImplClasses.containsKey( entityClass ) ){
            entityImplClasses.put( entityClass, createEntityImplClass( entityClass ) );
        }
    }

    /**
     *  新创建一个Entity对象
     * @param entityClass
     * @param <T>
     * @return
     */
    public static <T>  T  newEntity( Class<T> entityClass ){
        Class<?> implClass = entityImplClasses.get( entityClass );
        if ( implClass == null ) {
            EntityBuilder.registerEntity( entityClass );
            implClass = entityImplClasses.get( entityClass );
        }


        if( implClass != null ){
            try {
                return (T)implClass.newInstance();
            } catch ( Throwable e) {
                logger.error( "实体实例化失败" , e );
                return null;
            }
        }else{
            logger.error( "实体未注册:" + entityClass.getName()  );
            return null;
        }
    }


    private static Class<?> createEntityImplClass( Class<?> entityClass ){

        ClassGenerator cg = ClassGenerator.newInstance();

        cg.setClassName(entityClass.getName() + "$Impl");
        cg.setSuperClass(entityClass);

        Method[] methodArray =  entityClass.getDeclaredMethods();
        for( Method m : methodArray ){

            String methodName = m.getName( );

            //方法不能有返回值
            if( methodName.startsWith( "set" )  ){

                StringBuilder sb = new StringBuilder( );
                sb.append("public  void "  + methodName + "(");

                Class[] parameters =  m.getParameterTypes();
                for( int i = 0; i < parameters.length; i++ ){
                    if( i > 0 ){
                        sb.append( "," );
                    }
                    sb.append(  ReflectionUtils.getTypeName( m.getParameterTypes( )[ i ] ) + " p" + i );
                }
                sb.append( "){" );

                sb.append( "super." + methodName + "( " );
                for( int i = 0; i < parameters.length; i++ ){
                    if( i > 0 ){
                        sb.append( "," );
                    }
                    sb.append(  " p" + i );
                }
                sb.append( " );" );

                sb.append( "setDirty();" );
                sb.append("}");
                cg.addMethod( sb.toString() );

            }
        }

        cg.addDefaultConstructor();
        /*
        Constructor<?>[] constructors =  entityClass.getDeclaredConstructors();
        for( Constructor c : constructors ){
            cg.addConstructor( c );
        }
        */

        return cg.toClass();
    }



}
